package com.baize.baizeapp.test.video

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.content.pm.ActivityInfo
import android.graphics.SurfaceTexture
import android.util.AttributeSet
import android.util.Log
import android.util.LruCache
import android.view.LayoutInflater
import android.view.Surface
import android.view.TextureView
import android.view.View
import android.widget.FrameLayout
import android.widget.ImageView
import android.widget.SeekBar
import android.widget.TextView
import androidx.appcompat.widget.AppCompatSeekBar
import androidx.constraintlayout.widget.Group
import com.baize.baizeapp.R
import com.baize.baizeapp.utils.SPUtils
import com.bumptech.glide.Glide
import com.ss.ttvideoengine.*
import com.ss.ttvideoengine.TTVideoEngine
import com.ss.ttvideoengine.utils.Error
import java.security.MessageDigest


class HeiShiTTVideo @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleRes: Int = 0
) : FrameLayout(context, attrs, defStyleRes) {

    val displayMode = DisplayMode()
    var ttVideoEngine: TTVideoEngine? = null

    lateinit var textureView: TextureView
    lateinit var seekbar: AppCompatSeekBar
    lateinit var big_seekbar: AppCompatSeekBar
    lateinit var btn_loading: ImageView
    lateinit var group_pause: Group
    lateinit var btn_play: ImageView
    lateinit var tv_play_time: TextView
    lateinit var iv_orientation: ImageView
    lateinit var seekRunnable: Runnable

    //外部监听
    var ttViceoListener: TTVideoComposeEventListener? = null
    var currentPlayVideoAddress = ""

    init {
        ttVideoEngine = TTVideoEngine(context.applicationContext, TTVideoEngine.PLAYER_TYPE_OWN)
        initComponent()
        seekRunnable = Runnable {
            val currProcess = ttVideoEngine?.currentPlaybackTime ?: 0
            seekbar.setProgress(currProcess)
            big_seekbar.setProgress(currProcess)
            if (tv_play_time.visibility == View.VISIBLE) {
                updatePlayTimeDesc()
            }
            seekbar.postDelayed(seekRunnable, 200)
        }
        initPlayer()
    }

    fun initComponent() {
        val componentView = LayoutInflater.from(context).inflate(R.layout.video_component, this)
        //init texture
        textureView = componentView.findViewById(R.id.tt_textureView)
        displayMode.setContainerView(this)
        displayMode.setDisplayView(textureView)

        group_pause = componentView.findViewById(R.id.group_pause)
        btn_play = componentView.findViewById(R.id.btn_play)
        tv_play_time = componentView.findViewById(R.id.tv_play_time)
        iv_orientation = componentView.findViewById(R.id.iv_orientation)
        iv_orientation.setOnClickListener { fullChangeScreen() }
        componentView.setOnClickListener {
            updatePlayTimeDesc()
            if (ttViceoListener?.onVideoClickListener() == false) {
                return@setOnClickListener
            }
            when (ttVideoEngine?.playbackState) {
                TTVideoEngine.PLAYBACK_STATE_PLAYING -> ttVideoEngine?.pause()
                else -> ttVideoEngine?.play()
            }
        }
        //loading
        btn_loading = componentView.findViewById(R.id.btn_loading)
        Glide.with(this)
            .asGif()
            .load(R.drawable.loading)
            .into(btn_loading)
        //seekbar
        seekbar = componentView.findViewById(R.id.seekbar)
        big_seekbar = componentView.findViewById(R.id.big_seekbar)
        seekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                Log.i("yanze_seekbar", "onProgressChanged ${progress} fromUser:${fromUser}")
                if (fromUser) {
                    seekTo(progress) {
                        Log.i("yanze_video", "seekTo结果： ${it}")
                        updatePlayTimeDesc()
                    }
                    big_seekbar.setProgress(progress)
                }
            }

            override fun onStartTrackingTouch(s: SeekBar) {
                ttVideoEngine?.pause()
                big_seekbar.visibility = View.VISIBLE
                seekbar.visibility = View.INVISIBLE
                Log.i("yanze_seekbar", "onStartTrackingTouch")
            }

            override fun onStopTrackingTouch(s: SeekBar) {
                ttVideoEngine?.start()
                big_seekbar.visibility = View.INVISIBLE
                seekbar.visibility = View.VISIBLE
                Log.i("yanze_seekbar", "onStopTrackingTouch")
            }
        })
    }

    fun setComponentListener(listener: TTVideoComposeEventListener) {
        this.ttViceoListener = listener
    }

    //方向切换
    private fun fullChangeScreen() {
        (context as? Activity)?.run {
            requestedOrientation =
                if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) { // 切换为竖屏
                    setDisplayMode(DisplayMode.DISPLAY_MODE_ASPECT_FILL_X)
                    ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
                } else {
                    setDisplayMode(DisplayMode.DISPLAY_MODE_ASPECT_FILL_Y)
                    ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
                }
        }
    }

    fun backPressed(): Boolean {
        val activity = context as? Activity
        return if (activity != null && activity.requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
            fullChangeScreen()
            false
        } else {
            release()
            true
        }
    }

    fun startProcessRefresh() {
        seekbar.post(seekRunnable)
    }

    fun stopProcessRefresh() {
        seekbar.removeCallbacks(seekRunnable)
    }

    @SuppressLint("SetTextI18n")
    fun updatePlayTimeDesc() {
        tv_play_time.text =
            HeiShiTTVideoHelper.getDurationDesc(ttVideoEngine?.currentPlaybackTime ?: 0) + "/" +
                    HeiShiTTVideoHelper.getDurationDesc(ttVideoEngine?.duration ?: 0)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        displayMode.apply()
    }

    fun setDisplayMode(displayMode: Int) {
        this.displayMode.displayMode = displayMode
    }

    fun setUrl(videoUrl: String) {
        // enable MDL (数据加载模块)
        ttVideoEngine?.setIntOption(TTVideoEngine.PLAYER_OPTION_ENABLE_DATALOADER, 1)
        // 缓存key 推荐使用 url md5
        val key = HeiShiTTVideoHelper.md5(videoUrl)
        ttVideoEngine?.setDirectUrlUseDataLoader(videoUrl, key)
        currentPlayVideoAddress = videoUrl
    }

    fun setPath(path: String) {
        currentPlayVideoAddress = path
        ttVideoEngine?.setLocalURL(path)
    }

    fun seekTo(msec: Int, listener: ((Boolean) -> Unit)? = null) {
        if (msec in 1 until (ttVideoEngine?.duration ?: 1)) {
            Log.i("yanze_time", "seek to ${msec}")
            ttVideoEngine?.seekTo(msec, listener)
        }
    }

    fun play() {
        ttVideoEngine?.play()
    }

    fun pause() {
        ttVideoEngine?.pause()
    }

    fun stop() {
        cachePlayTime()
        ttVideoEngine?.stop()
    }

    fun isPlaying(): Boolean {
        return ttVideoEngine?.playbackState == TTVideoEngine.PLAYBACK_STATE_PLAYING
    }

    fun replayWithCacheTime() {
        val cacheTime = HeiShiTTVideoHelper.getCacheTIme(HeiShiTTVideoHelper.md5(currentPlayVideoAddress))
        Log.i("yanze_video","读取缓存时间:${cacheTime}")
        if (cacheTime in 1..(ttVideoEngine?.duration ?: 1)) {
            seekTo(cacheTime)
        }
    }

    fun cachePlayTime() {
        if (ttViceoListener?.isNeedCachePlayTime() != false) {
            val currTime = ttVideoEngine?.currentPlaybackTime ?: 0
            if (currTime > 0) {
                Log.i("yanze_video","缓存时间:${currTime}")
                HeiShiTTVideoHelper.save(HeiShiTTVideoHelper.md5(currentPlayVideoAddress), currTime)
            }
        }
    }

    fun initPlayer() {
        textureView.setKeepScreenOn(true); // 设置屏幕保持常亮
        ttVideoEngine?.isLooping = true
        //关联
        textureView.surfaceTextureListener = object : TextureView.SurfaceTextureListener {
            override fun onSurfaceTextureAvailable(
                surfaceTexture: SurfaceTexture,
                width: Int,
                height: Int
            ) {
                // TextureView 的 SurfaceTexture 创建完成回调
                ttVideoEngine?.surface = Surface(surfaceTexture)
            }

            override fun onSurfaceTextureSizeChanged(
                surfaceTexture: SurfaceTexture,
                width: Int,
                height: Int
            ) {
                Log.d("yanze_surface", "onSurfaceTextureSizeChanged:${width} ${height}")
            }

            override fun onSurfaceTextureDestroyed(surfaceTexture: SurfaceTexture): Boolean {
                return true
            }

            override fun onSurfaceTextureUpdated(surfaceTexture: SurfaceTexture) {
            }
        }
        //播放状态监听
        ttVideoEngine?.setListener(object : VideoEngineListener {
            override fun onPlaybackStateChanged(engine: TTVideoEngine?, playbackState: Int) {
                Log.i("yanze_video", "播放状态：onPlaybackStateChanged $engine $playbackState");
                // 播放状态改变回调
                when (playbackState) {
                    TTVideoEngine.PLAYBACK_STATE_PLAYING -> {
                        Log.i("yanze_video", "开始播放>>")
                        startProcessRefresh()
                        group_pause.visibility = View.GONE
                    }
                    TTVideoEngine.PLAYBACK_STATE_ERROR -> {
                        // Note:
                        // 1.本消息不代表本次播放失败，内部重试后可能会恢复播放
                        // 2.若最终播放失败，会在 VideoEngineListener#onError() 中回调
                        Log.i("yanze_video", "播放出错>>.")
                        stopProcessRefresh()
                        group_pause.visibility = View.VISIBLE
                    }
                    TTVideoEngine.PLAYBACK_STATE_STOPPED -> {
                        Log.i("yanze_video", "播放停止>>")
                        stopProcessRefresh()
                        group_pause.visibility = View.VISIBLE
                    }
                    TTVideoEngine.PLAYBACK_STATE_PAUSED -> {
                        Log.i("yanze_video", "播放暂停>>")
                        stopProcessRefresh()
                        group_pause.visibility = View.VISIBLE
                    }
                }
            }

            override fun onLoadStateChanged(engine: TTVideoEngine?, loadState: Int) {
                Log.v(
                    "yanze_video",
                    "加载状态：onLoadStateChanged " + engine.toString() + " " + loadState
                )
                when (loadState) {
                    TTVideoEngine.LOAD_STATE_PLAYABLE -> {
                        Log.i("yanze_video", "buffer end 完成缓冲")
                        btn_loading.visibility = View.GONE
                    }
                    TTVideoEngine.LOAD_STATE_STALLED -> {
                        btn_loading.visibility = View.VISIBLE
                        Log.i("yanze_video", "buffer start 开始缓冲")
                    }
                    TTVideoEngine.LOAD_STATE_ERROR -> {
                        btn_loading.visibility = View.GONE
                        Log.i("yanze_video", "load error")
                    }
                    else -> {
                    }
                }
            }

            override fun onVideoSizeChanged(p0: TTVideoEngine?, width: Int, height: Int) {
                // 播放器解析到视频宽高有变化时回调
                displayMode.setVideoSize(width, height)
                Log.i("yanze_video", "onVideoSizeChanged:${width} ${height}")
                replayWithCacheTime()
            }

            override fun onBufferingUpdate(engine: TTVideoEngine?, percent: Int) {
                // 缓存进度回调，可用于展示播放进度条上的二级缓存进度，取值1-100
                Log.d(
                    "yanze_video",
                    "缓存进度：onBufferingUpdate $engine $percent  ${seekbar.secondaryProgress}"
                )
                seekbar.secondaryProgress = percent * (ttVideoEngine?.duration ?: 0) / 100
            }

            override fun onPrepare(p0: TTVideoEngine?) {
                // prepare 时立刻回调
                Log.d("yanze_video", "prepare! onPrepare")
            }

            override fun onPrepared(video: TTVideoEngine?) {
                // prepare 完成后回调
                Log.d(
                    "yanze_video",
                    "prepared 完成! onPrepared ${video?.videoWidth} ${video?.videoHeight}"
                )
                if (ttViceoListener?.onChangeScreenButtonShow() != false
                    && video?.videoWidth ?: 0 > video?.videoHeight ?: 0
                ) {
                    iv_orientation.visibility = VISIBLE
                } else {
                    iv_orientation.visibility = GONE
                }
                displayMode.setVideoSize(
                    ttVideoEngine?.getVideoWidth() ?: 0,
                    ttVideoEngine?.getVideoHeight() ?: 0
                )
                seekbar.max = ttVideoEngine?.getDuration() ?: 100
                big_seekbar.max = ttVideoEngine?.getDuration() ?: 100
                seekbar.visibility = View.VISIBLE

                Log.i("yanze_video", "当前播放：${ttVideoEngine?.currentPlayPath}")
//                if (ttViceoListener?.isNeedCachePlayTime() != false) {
//                    val cacheTime = HeiShiTTVideoHelper.getCacheTIme(
//                        HeiShiTTVideoHelper.md5(
//                            currentPlayVideoAddress
//                        )
//                    )
//                    seekTo(cacheTime)
//                }
            }

            override fun onRenderStart(p0: TTVideoEngine?) {
                // 开始渲染时回调，可以认为此刻视频画面已经展示
            }

            override fun onStreamChanged(p0: TTVideoEngine?, p1: Int) {
                //音视频流变化通知
            }

            override fun onCompletion(p0: TTVideoEngine?) {
                //播放完成
                Log.d("yanze_video", "播放完成! onCompletion")
            }

            override fun onError(p0: Error?) {
                //播放错误
                Log.d("yanze_video", "播放错误! onError：${p0?.code}")
            }

            override fun onVideoStatusException(p0: Int) {
                Log.d("yanze_video", "播放异常! onVideoStatusException：${p0}")
            }
        })
        ttVideoEngine?.setVideoBufferListener(object : VideoBufferListener {
            override fun onBufferStart(code: Int) {
                Log.d("yanze_video", "onBufferStart $code")
            }

            override fun onBufferEnd(code: Int) {
                Log.d("yanze_video", "onBufferEnd $code")
            }
        })
    }

    fun release() {
        ttVideoEngine?.let {
            if (ttViceoListener?.isNeedCachePlayTime() != false) {
                val currTime = it.currentPlaybackTime
                HeiShiTTVideoHelper.save(HeiShiTTVideoHelper.md5(currentPlayVideoAddress), currTime)
                Log.i("yanze_time", "save seek time ${currTime}")
            }
            stopProcessRefresh()
            it.release()
//            ttVideoEngine = null
        }
    }

}


object HeiShiTTVideoHelper {

    //最多支持50个视频的播放时长缓存 key：url的md5  value：时长
    private val lruCache = LruCache<String, Int>(50)

    fun save(key: String, value: Int) {
        if (value == 0) {
            lruCache.remove(key)
            return
        }
        lruCache.put(key, value)
    }

    fun getCacheTIme(key: String): Int {
        return lruCache.get(key) ?: 0
    }

    fun md5(str: String): String {
        val digest = MessageDigest.getInstance("MD5")
        val result = digest.digest(str.toByteArray())
        //没转16进制之前是16位
        println("result${result.size}")
        //转成16进制后是32字节
        return toHex(result)
    }

    fun toHex(byteArray: ByteArray): String {
        val result = with(StringBuilder()) {
            byteArray.forEach {
                val hex = it.toInt() and (0xFF)
                val hexStr = Integer.toHexString(hex)
                if (hexStr.length == 1) {
                    this.append("0").append(hexStr)
                } else {
                    this.append(hexStr)
                }
            }
            this.toString()
        }
        //转成16进制后是32字节
        return result
    }

    //返回格式：15:05
    fun getDurationDesc(duration: Int): String {
        if (duration == 0) return "00:00"
        val minutes = (duration / 1000 / 60)
        val seconds = (duration / 1000 % 60)
        return "${format(minutes)}:${format(seconds)}"
    }

    fun format(digital: Int): String {
        return if (digital in 0..9) "0${digital}"
        else "$digital"
    }
}


interface TTVideoComposeEventListener {
    //视频单击事件，返回值：是否继续触发默认事件（播放，暂停）
    fun onVideoClickListener(): Boolean {
        return true
    }

    //是否缓存上次播放时间（内存缓存）
    fun isNeedCachePlayTime(): Boolean {
        return true
    }

    //展示横竖屏切换按钮
    fun onChangeScreenButtonShow(): Boolean {
        return true
    }
}


















